package com.starry.core.tenant.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.starry.core.common.constants.WebFilterOrderEnum;
import com.starry.core.tenant.core.aop.TenantIgnoreAspect;
import com.starry.core.tenant.core.db.TenantDatabaseInterceptor;
import com.starry.core.tenant.core.mq.TenantRabbitMQInitializer;
import com.starry.core.tenant.core.security.TenantSecurityWebFilter;
import com.starry.core.tenant.core.service.TenantFrameworkService;
import com.starry.core.tenant.core.web.TenantContextWebFilter;
import com.starry.core.web.core.web.execption.GlobalExceptionHandler;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import java.util.ArrayList;
import java.util.List;

/**
 * 租户配置
 *
 * @author xiaoke
 */
@ConditionalOnProperty(value = "enable", matchIfMissing = true)
@AutoConfiguration
@EnableAspectJAutoProxy
public class TenantAutoConfiguration {

    /**
     * 添加租户插件
     */
    @Bean
    public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
                                                                 MybatisPlusInterceptor interceptor) {
        TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
        // 需要加在首个，主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
        List<InnerInterceptor> inners = new ArrayList<>(interceptor.getInterceptors());
        inners.add(0, inner);
        interceptor.setInterceptors(inners);
        return inner;
    }


    // ========== AOP ==========

    @Bean
    public TenantIgnoreAspect tenantIgnoreAspect() {
        return new TenantIgnoreAspect();
    }

    /// /////////////WEB////////////////
    @Bean
    public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
        FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TenantContextWebFilter());
        registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
        return registrationBean;
    }

    /// /////////////Security////////////////
    @Bean
    public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(
            TenantProperties tenantProperties,
            TenantFrameworkService tenantFrameworkService,
            GlobalExceptionHandler exceptionHandler
    ) {
        FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, tenantFrameworkService, exceptionHandler));
        registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
        return registrationBean;
    }

    @Bean
    @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
    public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
        return new TenantRabbitMQInitializer();
    }
}
